#include "Input.h"


Input::Input(HWND hWnd)
{
	_hWnd = hWnd;
	_dinput = NULL;
	_dikeyboard = NULL;
}


Input::~Input()
{
	if (_dinput != NULL) _dinput->Release();

	if (_dikeyboard != NULL)
	{
		_dikeyboard->Unacquire();
		_dikeyboard->Release();
		_dikeyboard = NULL;
	}
}

bool Input::InitDirectInput()
{
	// initialize DirectInput object
	HRESULT result = DirectInput8Create(GetModuleHandle(NULL),
		DIRECTINPUT_VERSION,
		IID_IDirectInput8,
		(void**)&_dinput,
		NULL);

	if (result != DI_OK)
		return false;

	// intialize the keyboard
	result = _dinput->CreateDevice(GUID_SysKeyboard, &_dikeyboard, NULL);

	if (result != DI_OK)
		return false;

	//set the data format for mouse input
	result = _dikeyboard->SetDataFormat(&c_dfDIKeyboard);

	if (result != DI_OK)
		return false;

	// set the cooperation level
	result = _dikeyboard->SetCooperativeLevel(_hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);

	if (result != DI_OK)
		return false;

	DIPROPDWORD dipdw;

	dipdw.diph.dwSize = sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipdw.diph.dwObj = 0;
	dipdw.diph.dwHow = DIPH_DEVICE;
	dipdw.dwData = KEYBOARD_BUFFER_SIZE; // Arbitary buffer size

	result = _dikeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);

	if (result != DI_OK)
		return false;

	// acquire the keyboard
	result = _dikeyboard->Acquire();

	if (result != DI_OK)
		return false;

	_keydown = 0;
	_keyup = 0;

	return true;
}

void Input::ProcessKeyboard()
{
	// Poll state of the keyboard
	_dikeyboard->Poll();

	// Keyboard decive lost, try to re-acquire
	if (!SUCCEEDED(_dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys)))
	{
		_dikeyboard->Acquire();
	}

	// Collect all key states first
	_dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);

	// Collect all bufferd events
	DWORD dwElements = KEYBOARD_BUFFER_SIZE;
	HRESULT hr = _dikeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), _keyEvents, &dwElements, 0);

	// Scan through all data, check if the key is pressed or released
	for (DWORD i = 0; i < dwElements; i++)
	{
		int KeyCode = _keyEvents[i].dwOfs;
		int KeyState = _keyEvents[i].dwData;

		if ((KeyState & 0x80) > 0)
			_keydown = KeyCode;
		else
			_keyup = KeyCode;
	}
}

int Input::KeyDown(int key)
{
	return (keys[key] & 0x80);
}

int Input::OnKeyDown()
{
	int temp = _keydown;
	_keydown = 0;
	return temp;
}

int Input::OnKeyUp()
{
	int temp = _keyup;
	_keyup = 0;
	return temp;
}

